package handler

import (
	"encoding/json"
	"gitee.com/baidugoogle/ccu/src/handler/protocol"
	"gitee.com/baidugoogle/ccu/src/ulog"
	"gitee.com/baidugoogle/ccu/src/util"
	"golang.org/x/net/websocket"
	"io"
	"net"
	"time"
)

const RTCWebsocketReadTimeout = 25 * time.Second //
const RTCReadMaxTime = 30 * time.Minute

func RtcWebsocketConnHandle(ws *websocket.Conn) {
	var wsCli = &protocol.WebsocketConnection{
		ConnId: util.NewUidMD5To16("cid"),
		Conn:   ws,
	}
	protocol.ClientConnList.Store(wsCli)

	defer func() {
		ulog.Info("close websocket %v", wsCli.ConnId)
		protocol.ClientConnList.Delete(wsCli.ConnId)
	}()

	var err error
	var msg = &protocol.WsClientMsg{}
	for true {
		// 设置读超时
		err = ws.SetReadDeadline(time.Now().Add(RTCWebsocketReadTimeout))
		if err != nil {
			return
		}

		// 读取消息
		if err = websocket.JSON.Receive(ws, msg); err != nil {
			if err == io.EOF {
				ulog.Info("EOF")
				break
			}

			if ne, ok := err.(*net.OpError); ok {
				if ne.Timeout() {
					// 接收超时, 正常现象, 发送ping frame
					mSendPingFrame(wsCli)
				} else {
					// 其它的错误, 不能容忍, 果断断开
					ulog.Error("recv json msg fail [%v]", err)
					break
				}
			}

			continue
		}

		ulog.Info("recv msg: %v", msg)

		// 广播数据
		protocol.ClientConnList.Range(func(conn *protocol.WebsocketConnection) bool {
			if conn.ConnId != wsCli.ConnId {
				mSendMsg(conn, msg)
			}
			return true
		})
	}
}

// mSendPingFrame 发送ping数据
func mSendPingFrame(cli *protocol.WebsocketConnection) {
	ws := cli.Conn
	if pingFrameWriter, err := ws.NewFrameWriter(websocket.PingFrame); err == nil {
		_, _ = pingFrameWriter.Write([]byte("ping frame"))
		_ = pingFrameWriter.Close()
	}
}

func mSendMsg(cli *protocol.WebsocketConnection, msg *protocol.WsClientMsg) {
	data, _ := json.Marshal(msg)

	ulog.Info("send msg: %v", string(data))

	_, err := cli.Conn.Write(data)
	if err != nil {
		ulog.Error("send msg fail %v", err)
	}
}
